#pragma once

#include "PLObject.h"
#include "PLVec2.h"

#include <map>
#include <set>

class PLEdge;

/**
  *	A PLVertex object is a vertex that is defined by the vertex index, texcoord
  * index and texture ID. Therefore it is possible that a single vertex in the model
  * is represented by more than one PLVertex object, which is the case, when the
  * vertex is mapped into more than one image.
  */
class PLVertex : public PLObject
{
	friend PLEdge;

public:
	PLVertex( PLuint vertexIndex = 0U, PLuint texcoordIndex = 0U,
		PLuint textureID = 0U );
	virtual ~PLVertex( void );

	void AddAdjacentVertex( PLVertex *adjacentVertex );

	const std::set<PLVertex *> *GetAdjacentVertexes( void ) const;

	const PLVec2d *GetNormal( const PLuint &blobID ) const;

	const double &GetLevellingR( void ) const;
	const double &GetLevellingG( void ) const;
	const double &GetLevellingB( void ) const;
	const double *GetLevellingBGR( void ) const;

	const double &GetOriginalR( void ) const;
	const double &GetOriginalG( void ) const;
	const double &GetOriginalB( void ) const;
	const double *GetOriginalBGR( void ) const;

	const PLuint &GetTexcoordIndex( void ) const;
	const PLuint &GetTextureID( void ) const;
	const PLuint &GetVertexIndex( void ) const;

	static const PLuint &GetNumVertexes( void );

	void SetLevellingR( const double &levellingR );
	void SetLevellingG( const double &levellingG );
	void SetLevellingB( const double &levellingB );

	void SetLevellingColorBGR( const double *bgr );
	void SetOriginalColorBGR( const double *bgr );
	void SetNormal( const PLVec2d &normal, const PLuint &blobID );

	/**
	  *	A PLVertexCompare object is used as a Compare object in an stl container
	  */
	static class PLVertexCompare
	{
		public:
			bool operator()(const PLVertex &first, const PLVertex &second) const;
	};

	/**
	  *	A PLVertexPCompare object is used as a Compare object in an stl container
	  */
	static class PLVertexPCompare
	{
		public:
			bool operator()(const PLVertex *first, const PLVertex *second) const;
	};

private:
	/** Vertex index */
	PLuint mVertexIndex;
	/** Texcoord index */
	PLuint mTexcoordIndex;
	/** Unique texture ID */
	PLuint mTextureID;

	/** Original color of the vertex, which is the color of the image at the sample position */
	double mOriginalBGR[3];
	/** Leveling values for all channels */
	double mLevellingBGR[3];

	/** Set of all the adjacent vertexes in the other PLBlob objects */
	std::set<PLVertex *> *mAdjacentVertexes;
	/** Number of vertexes, that are currently instantiated */
	static PLuint mNumVertexes;
	/** Map, that maps PLBlob IDs to the corresponding normal vector */
	std::map<PLuint, PLVec2d> *mBlobIDToNormalMap;
};